#include <iostream>
#include <string>
#include <crafter.h>

/* Collapse namespaces */
using namespace std;
using namespace Crafter;

int main(){
        
       
       //Set the interface 
        string iface = "wlan0";
        
        string MyIP = GetMyIP(iface);
        /* Get the MAC Address associated to the interface */
        string MyMAC = GetMyMAC(iface);

        Ethernet ether_header;

        ether_header.SetSourceMAC(MyMAC);
        ether_header.SetDestinationMAC("ff:ff:ff:ff:ff:ff");

                   
        //Get the IP address associated to the interface 
      
        cout << "[@] My IP address is  : " << MyIP  << endl;

        // Create an IP header 
        IP ip_header;
        // Set the Source and Destination IP address 
        ip_header.SetSourceIP(MyIP);
        ip_header.SetDestinationIP("192.168.1.2");

        // Create an TCP - SYN header 
        TCP tcp_header;
        
        tcp_header.SetSrcPort(4788);
        tcp_header.SetDstPort(3000);
        tcp_header.SetSeqNumber(1);
        tcp_header.SetAckNumber(1);
        tcp_header.SetFlags(TCP::SYN);
        // Create a packets
        tcp_header.SetPayload("Go ITT");
        Packet tcp_packet = ether_header / ip_header / tcp_header;
        
        /* Bind to interface */

        
         int s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);

         if(s < 0)
        {
                Crafter::PrintMessage(Crafter::PrintCodes::PrintPerror,
                                     "CreateRawSocket()",
                             "Creating raw(PF_INET) socket");
                exit(1);
        }

        /* Sock options */
        int one = 1;
        const int* val = &one;

        if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
                PrintMessage(Crafter::PrintCodes::PrintError,
                                        "Packet::RawSocketSend()",
                                        "Setting IP_HDRINCL option to raw socket");
                exit(1);
        }

        if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, val, sizeof(one)) < 0) {
                PrintMessage(Crafter::PrintCodes::PrintError,
                                        "Packet::RawSocketSend()",
                                        "Setting SO_BROADCAST flag to raw socket");
                exit(1);
        }

        
        ifreq Interface;
        memset(&Interface, 0, sizeof(Interface));
        strncpy(Interface.ifr_ifrn.ifrn_name, iface.c_str(), IFNAMSIZ);
        if (ioctl(s, SIOCGIFINDEX, &Interface) < 0)
        {
                Crafter::PrintMessage(Crafter::PrintCodes::PrintPerror,
                                     "BindRawSocketToInterface()",
                             "Binding raw socket to interface");
                exit(1);
        }

        tcp_packet.SocketSendRecv(s,iface); 
        tcp_packet.Print();
        return 0;
        
}